//进程池实现能够给服务器的cgi模式提供已经在运行的进程，从而可以节省
//cgi模式下fork的时间开支，进程池需要做的事情：
//1.接受来自服务器传输过来的prama参数，根据不同的参数进行不同的计算
//先考虑在本主机模式，不考虑多主机模式


#ifndef __PROCESS_POOL_SELF__
#define __PROCESS_POOL_SELF__

#define IPC_SHM_KET 0x12345678
#define IPC_SEM_KET 0x22345678

#include <iostream>
#include <queue>
#include <string>
#include <vector>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>

//实现的cgi程序随着需求的增多而发生变化

#define CAL 1
#define LOGIN 2
#define LOGOUT 3

#define NUM 5


class FunctionUtil{
    static void cal(std::string& prama){
        //计算的cgi
    }

    static void login(std::string& prama)
    {
        //登录的cgi
    }

    static void logout(std::string& prama)
    {
        //注册的cgi
    }
};//cgi中给的几种，便于后期维护和升级

class cgi{
public:
    cgi(){};

    static void Handle(int flags, std::string& prama)
    {
        switch(flags){
            case CAL:
                FunctionUtil::cal(prama);
                break;
            case LOGIN:
                FunctionUtil::login(prama);
                break;
            case LOGOUT:
                FunctionUtil::logout(prama);
                return;
        }
    }
};

class Task{
public:
    Task(){}

    static void SetTask(std::string& prama)
    {
        //初步拟定直接在这个函数进行对prama的解析，可以适当减轻主服务器的负担
        std::size_t pos_ = prama.rfind("&");
        if(pos_ == std::string::npos){
            std::cout<<"sorry, the way which you submit is not found"<<std::endl;
            return;
        }
        std::string flags_ = prama.substr(pos_);
        if(strcasecmp(flags_.c_str(), "CAL") == 0)
        {
            cgi::Handle(CAL, prama.substr(0, prama.size() - pos_));
        }
        else if(strcasecmp(flags_.c_str(), "LOGIN") == 0)
        {
            cgi::Handle(LOGIN, prama.substr(0, prama.size() - pos_));
        }
        else if(strcasecmp(flags_.c_str(), "LOGOUT") == 0)
        {
            cgi::Handle(LOGOUT, prama.substr(0, prama.size() - pos_));
        }
        else
        {
            std::cout<<"ERROR"<<std::endl;
        }
    }
};

union semnu{
   int val;
   struct semid_ds *buf;
   unsigned short *array;
   struct seminfo *__buf;
};

class ProcessPool{
private:
    ProcessPool()
    {}
    
    int shmid;//共享内存集合
    int semid;//信号量集合
    std::vector<int> v_process;

public:
    void InitProcessPool(int num_= NUM)
    {
        //每个进程都要打开或创建共享内存
        shmid = shmget(IPC_SHM_KEY, 4096, IPC_CREAT|0664);
        void* shm_start = shmat(shmid, NULL, 0);

        //每个进程都要打开或创建信号量
        semid = semget(IPC_SEM_KEY, 1, IPC_CREAT|0664);
        union semnu val;
        val.val = 1;
        semctl(semid, 0, SETVAL, val);
        

        pid_t pid = -1;
        for(int i = 0; i < num_; ++i){
            pid = fork();
            if(pid == -1)
            {
                std::cout<<"create child process error!"<<std::endl;
                return;
            }
            else if(pid == 0)
            {
                std::cout<<"child process has been created!"<<std::endl;
                break;
            }
            v_process.push_back(pid);
            continue;
        }//创建多个进程

        if(pid > 0)
        {
                                            
        }
        else
        {
            
        }
    }

    void lock()
    {
        struct sembuf buf;
        buf.sem_num = 0;
        buf.sem_op = -1;
        buf.sem_flg = SEM_UNDO;

        semop(semid, &buf, 1);
    }//P操作

    void unlock()
    {
        struct sembuf buf;
        buf.sem_num = 0;
        buf.sem_op =  1;
        buf.sem_flg = SEM_UNDO;

        semop(semid, &buf, 1);
    }//V操作
    
    //将prama放入共享内存当中变成公共资源，只有主进程有资格调用此接口
    void PramaToSharedMem()
    {
        
    }
};








